package com.google.code.b0rx0r.ui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.GroupLayout;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.google.code.b0rx0r.PlayQueue;
import com.google.code.b0rx0r.program.Sequence;

public class SequencePanel extends BasicComponent implements Previewable {
	private Sequence sequence;
	
  private Sequencer sequencer = new Sequencer(getMain());

  private JSpinner  spBars = new JSpinner(new SpinnerNumberModel(1, 1, 16, 1));
  private JSpinner  spBeats = new JSpinner(new SpinnerNumberModel(4, 1, 32, 1));
  private JSpinner  spSnappoints = new JSpinner(new SpinnerNumberModel(4, 1, 32, 1));
  
  private JSpinner  spBPM = new JSpinner(new SpinnerNumberModel(220d, 0d, 1000d, 1.0d));
  private JCheckBox cbSyncToHost = new JCheckBox(new AbstractAction(Messages.getString("SequencePanel.fromHost")) { //$NON-NLS-1$
		@Override
		public void actionPerformed(ActionEvent e) {
			boolean set = cbSyncToHost.isSelected();
			spBPM.setEnabled(!set);
			if (sequence != null) {
				sequence.setSyncToHostTempo(set);
			}
		}
  });
  
  public SequencePanel(MainPane main) {
  	super(main);
  	initGui();
  }

	private void initGui() {
		JScrollPane spSequencer = new JScrollPane(sequencer);
		setLayout(new BorderLayout());
		add(spSequencer, BorderLayout.CENTER);

		
		JLabel lTempo = new JLabel(Messages.getString("SequencePanel.Tempo")); //$NON-NLS-1$
		JLabel lBPM = new JLabel(Messages.getString("SequencePanel.BPM")); //$NON-NLS-1$
		JLabel lBars = new JLabel(Messages.getString("SequencePanel.Bars")); //$NON-NLS-1$
		JLabel lBeats = new JLabel(Messages.getString("SequencePanel./4")); //$NON-NLS-1$
		JLabel lSnappoints = new JLabel(Messages.getString("SequencePanel.SnappointsPerBar")); //$NON-NLS-1$
		
		JPanel pDetails = new JPanel();
		add(pDetails, BorderLayout.SOUTH);
		
		GroupLayout layout = new GroupLayout(pDetails);

		layout.setVerticalGroup(layout.createSequentialGroup().addGroup(layout.createParallelGroup().addComponent(lTempo)
				                                                                                        .addComponent(spBPM)
				                                                                                        .addComponent(lBPM)
				                                                            )
				                                                  
				                                                  .addComponent(cbSyncToHost)
				                                                  		     
				                                                  .addGap(5)
				                                                  .addGroup(layout.createParallelGroup().addComponent(spBars)
				                                                  		                                  .addComponent(lBars)
				                                                  		     )
				                                                  .addGroup(layout.createParallelGroup().addComponent(spBeats)
                                		                                                            .addComponent(lBeats)
                                		                                )
          				                                        .addGroup(layout.createParallelGroup().addComponent(spSnappoints)
        		                                                                                    .addComponent(lSnappoints)
        		                                )
		);
		
		layout.setHorizontalGroup(
				layout.createSequentialGroup()
				  .addComponent(lTempo)
				  .addGroup(layout.createParallelGroup()
				  		.addComponent(spBPM)
				  		.addComponent(cbSyncToHost)
				  		.addComponent(spBars)
				  		.addComponent(spBeats)
				  		.addComponent(spSnappoints)
				  		)
				  .addGroup(layout.createParallelGroup()
				  		.addComponent(lBPM)
				  		.addGap(0)
				  		.addComponent(lBars)
				  		.addComponent(lBeats)
				  		.addComponent(lSnappoints)
				  		)
		);
		
		
		spBPM.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				if (sequence != null)
					sequence.setTempoBPM(((Number)spBPM.getValue()).floatValue());
			}
		});
		
		spBars.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				if (sequence != null)
					sequence.setLengthBars(((Number)spBars.getValue()).intValue());
			}
		});
		
		spBeats.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				if (sequence != null)
					sequence.setBeatsPerBar(((Number)spBeats.getValue()).intValue());
			}
		});		

		spSnappoints.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				if (sequence != null)
					sequence.setSnappointsPerBar(((Number)spSnappoints.getValue()).intValue());
			}
		});		
	}

	public void setSequence(Sequence s) {
		this.sequence = s;
		cbSyncToHost.setSelected(s.isSyncToHostTempo());
		spBPM.setValue(s.getTempoBPM());
		spBPM.setEnabled(!s.isSyncToHostTempo());
		
		spBars.setValue(s.getLengthBars());
		spBeats.setValue(s.getBeatsPerBar());
		spSnappoints.setValue(s.getSnappointsPerBar());
		
		sequencer.setSequence(s);
	}

	@Override
	public void triggerPreview(PlayQueue pq) {
		sequencer.triggerPreview(pq);
	}
}
